package cn.itcast.demo;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;

public class TestIndexReader {


    @Test
    public void testIndexReader() throws IOException, ParseException {



        //用来转换查询条件到对象的,创建索引的分词器一定要和查询索引的分词器一致
        QueryParser queryParser = new QueryParser("title",new IKAnalyzer());

        //把查询条件转换为查询条件对象
        Query query = queryParser.parse("谷歌地图");

        commonSearch(query);

    }



    @Test
    public void testMultiIndexReader() throws IOException, ParseException {


        //用来转换查询条件到对象的,创建索引的分词器一定要和查询索引的分词器一致

        //多字段转换工具
        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(new String[]{"id","title"},new IKAnalyzer());

        //把查询条件转换为查询条件对象
        Query query = queryParser.parse("3");


        commonSearch(query);

    }


    @Test
    public void testTermQueryIndex() throws IOException {
        //创建词条查询条件，词条查询不会继续分词，所以词库中有这个词才能查到，没有则查不到
        Query query = new TermQuery(new Term("title","谷歌地图"));

        commonSearch(query);
    }

    /*
     * 测试通配符查询
     * 	? 代表一个任意字符
     * 	* 代表0个或多个任意字符
     */


    @Test
    public void testWildcardQueryIndex() throws IOException {
        //通配符查询
        Query query = new WildcardQuery(new Term("title","谷歌*"));

        commonSearch(query);
    }

    @Test
    public void testFuzzyQueryIndex() throws IOException {
        //模糊查询 默认的最大编辑距离，可以改两次,可以修改最大编辑距离，由于最大编辑距离的取值范围为0-2，所以赋值只能是0，1，2
        Query query = new FuzzyQuery(new Term("title","facabook"),1);

        commonSearch(query);
    }

    @Test
    public void testNumericRangeQueryIndex() throws IOException {

        //当字段类型为数值类型


        //创建数据范围查询条件，5个参数，分别为，属性名称，最小值，最大值，是否包含最小值,是否包含最大值，
        Query query = NumericRangeQuery.newLongRange("id",2L,4L,true,true);

        commonSearch(query);
    }


    /**
     * MUST VS MUST   &&
     *
     * SHOULD VS SHOULD ||
     *
     * MUST_NOT
     *
     *
     * @throws IOException
     */
    @Test
    public void testBooleanQueryIndex() throws IOException {

        //组合查询  && || ！


        //创建数据范围查询条件，5个参数，分别为，属性名称，最小值，最大值，是否包含最小值,是否包含最大值，
        Query query1 = NumericRangeQuery.newLongRange("id",3L,5L,true,true);
        Query query2 = NumericRangeQuery.newLongRange("id",2L,4L,true,true);

        BooleanQuery query = new BooleanQuery();

       query.add(query1, BooleanClause.Occur.MUST);
       query.add(query2, BooleanClause.Occur.MUST_NOT);

        commonSearch(query);
    }



    public void commonSearch(Query query) throws IOException {
        //Directory 访问目录对象
        Directory directory = FSDirectory.open(new File("indexDir"));

        //需要一个对象进行io操作把目录对象中的内容读取出来
        //indexReader也应该实现动态
        IndexReader indexReader = DirectoryReader.open(directory);


        //创建索引的搜索对象
        IndexSearcher searcher = new IndexSearcher(indexReader);




        //query表示查询条件对象，n表示用户最大期待的数据的量（如果匹配的量大于这个数字，则取前n条）
        //topDocs表示查询到的前n个文档的集合
        TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);

        //本次查询命中的个数
        int totalHits = topDocs.totalHits;

        System.out.println("命中了： " + totalHits);

        //查询到的文档的集合数组
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;

        for (ScoreDoc scoreDoc : scoreDocs) {
            //获取文档的得分
            float score = scoreDoc.score;

            //获取文档的编号
            int doc = scoreDoc.doc;

            //根据文档编号获取文档
            Document document = searcher.doc(doc);

            String id = document.get("id");
            String title = document.get("title");

            System.out.println("score: " +score+" id:"+id+" title:"+title);

        }

    }
}
